package cn.iocoder.yudao.module.resource.service.audio;

import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.infra.service.file.FileService;
import cn.iocoder.yudao.module.infra.service.file.UploadFileResult;
import cn.iocoder.yudao.module.resource.api.enums.EnumAudioRelationType;
import cn.iocoder.yudao.module.resource.controller.admin.audio.vo.AudioBaseRespVo;
import cn.iocoder.yudao.module.resource.controller.admin.audio.vo.AudioRelationRespVo;
import cn.iocoder.yudao.module.resource.controller.admin.audio.vo.AudioRelationSaveVo;
import cn.iocoder.yudao.module.resource.controller.admin.audio.vo.LmAudioPageReqVO;
import cn.iocoder.yudao.module.resource.controller.admin.audio.vo.LmAudioRespVO;
import cn.iocoder.yudao.module.resource.controller.admin.audio.vo.LmAudioSaveReqBatchVO;
import cn.iocoder.yudao.module.resource.controller.admin.audio.vo.LmAudioSaveReqVO;
import cn.iocoder.yudao.module.resource.controller.admin.audio.vo.UploadAudioBatchParam;
import cn.iocoder.yudao.module.resource.controller.admin.keyword.vo.KeyWordRespVO;
import cn.iocoder.yudao.module.resource.dal.dataobject.audio.LmAudioDO;
import cn.iocoder.yudao.module.resource.dal.dataobject.keyword.KeyWordDO;
import cn.iocoder.yudao.module.resource.dal.mysql.audio.LmAudioMapper;
import cn.iocoder.yudao.module.resource.dal.mysql.audio.model.LmAudioPageReq;
import cn.iocoder.yudao.module.resource.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.resource.service.audiomark.AudioMarkService;
import cn.iocoder.yudao.module.resource.service.keyword.KeyWordService;
import cn.iocoder.yudao.module.resource.service.tag.TagService;
import com.alibaba.fastjson.JSON;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.resource.enums.ErrorCodeConstants.AUDIO_NOT_EXISTS;

/**
 * 音频 Service 实现类
 *
 * @author wgs
 */
@Service
@Validated
public class LmAudioServiceImpl implements LmAudioService {

    @Resource
    private LmAudioMapper audioMapper;

    @Resource
    private FileService fileService;
    @Resource
    private KeyWordService keyWordService;
    @Resource
    private TagService tagService;
    @Resource
    private AudioMarkService audioMarkService;


    private void checkRelation(LmAudioSaveReqVO createReqVo) {
        int relationType = createReqVo.getRelationType();
        EnumAudioRelationType.checkHasType(relationType);
        if (relationType == EnumAudioRelationType.QUESTION_ANSWER.getType()) {
            if (createReqVo.getAudioRelationList() == null || createReqVo.getAudioRelationList().isEmpty()) {
                throw new ServiceException(ErrorCodeConstants.AUDIO_RELATION_EMPTY);
            }
            int defaultCount = 0;
            for (AudioRelationSaveVo audioRelationSaveVo : createReqVo.getAudioRelationList()) {
                if (!audioRelationSaveVo.isDefaultCon()) {
                    defaultCount++;
                    if (audioRelationSaveVo.getIds() == null || audioRelationSaveVo.getIds().isEmpty()) {
                        throw new ServiceException(ErrorCodeConstants.AUDIO_RELATION_KEY_WORD_EMPTY);
                    }
                }
                if (audioRelationSaveVo.getAudioId() == null) {
                    throw new ServiceException(ErrorCodeConstants.AUDIO_RELATION_KEY_AUDIO_EMPTY);
                }
                LmAudioDO audio = this.getAudio(audioRelationSaveVo.getAudioId());
                if (audio == null) {
                    throw new ServiceException(AUDIO_NOT_EXISTS);
                }
            }
            //if (defaultCount == 0) {
            //     throw new ServiceException(ErrorCodeConstants.AUDIO_RELATION_DEFAULT_EMPTY);
            // }

        }
    }

    @Override
    @Transactional
    public Integer createAudio(LmAudioSaveReqVO createReqVO) {
        this.checkRelation(createReqVO);
        fileService.checkFileExist(createReqVO.getFileId());
        keyWordService.checkKeyWordExist(createReqVO.getKeyWordIdArray());
        tagService.checkTagExist(createReqVO.getTagIdArray());
        // 插入
        LmAudioDO audio = BeanUtils.toBean(createReqVO, LmAudioDO.class);
        if (createReqVO.getAudioRelationList() != null) {
            audio.setRelationContent(JSON.toJSONString(createReqVO.getAudioRelationList()));
        }
        audioMapper.insert(audio);
        audioMarkService.updateAudioMark(audio.getId(), createReqVO.getTagIdArray(), createReqVO.getKeyWordIdArray());
        // 返回
        return audio.getId();
    }

    @Override
    public List<Integer> createAudioBatch(LmAudioSaveReqBatchVO saveReqBatchVO) {
        List<Integer> audioList = new ArrayList<>();
        for (UploadAudioBatchParam batchVO : saveReqBatchVO.getFileList()) {
            fileService.checkFileExist(batchVO.getFileId());
            LmAudioDO audioDO = new LmAudioDO();
            audioDO.setName(batchVO.getFileName());
            audioDO.setFileId(batchVO.getFileId());
            audioDO.setTextDesc(batchVO.getFileName());
            audioDO.setAudioToneId(saveReqBatchVO.getAudioToneId());

            audioDO.setAudioTime((int) batchVO.getAudioSize());
            audioMapper.insert(audioDO);
            audioList.add(audioDO.getId());
            // 存储标签
            if (saveReqBatchVO.getTagIdArray() != null) {
                audioMarkService.updateAudioMark(audioDO.getId(), saveReqBatchVO.getTagIdArray(), null);
            }
        }
        return audioList;
    }

    @Override
    @Transactional
    public void updateAudio(LmAudioSaveReqVO updateReqVO) {
        // 校验存在
        validateAudioExists(updateReqVO.getId());
        // 更新
        LmAudioDO updateObj = BeanUtils.toBean(updateReqVO, LmAudioDO.class);
        if (updateReqVO.getAudioRelationList() != null) {
            updateObj.setRelationContent(JSON.toJSONString(updateReqVO.getAudioRelationList()));
        }
        audioMapper.updateById(updateObj);
        audioMarkService.updateAudioMark(updateReqVO.getId(), updateReqVO.getTagIdArray(), updateReqVO.getKeyWordIdArray());
    }

    @Override
    public void deleteAudio(Integer id) {
        // 校验存在
        validateAudioExists(id);
        // 删除
        audioMapper.deleteById(id);
        // 删除标记
        this.audioMarkService.deleteByAudioId(id);
    }

    @Override
    public void deleteAudio(List<Integer> id) {
        audioMapper.deleteBatchIds(id);
        this.audioMarkService.deleteByAudioIds(id);
    }

    private void validateAudioExists(Integer id) {
        if (audioMapper.selectById(id) == null) {
            throw exception(AUDIO_NOT_EXISTS);
        }
    }

    @Override
    public LmAudioDO getAudio(Integer id) {
        return audioMapper.selectById(id);
    }

    @Override
    public List<LmAudioDO> getAudioByIds(Collection<Integer> id) {
        return audioMapper.selectBatchIds(id);
    }

    @Override
    public PageResult<LmAudioDO> getAudioPage(LmAudioPageReqVO pageReqVO) {
        List<Integer> audioIdList = null;
        if (StringUtils.isNotEmpty(pageReqVO.getTagName())) {
            audioIdList = new ArrayList<>();
            List<Integer> audioIdByTag = audioMarkService.getAudioIdListByTag(Arrays.asList(pageReqVO.getTagName()));
            audioIdList.addAll(audioIdByTag);
        }
        if (StringUtils.isNotEmpty(pageReqVO.getKeyWord())) {
            if (audioIdList == null) {
                audioIdList = new ArrayList<>();
            }
            List<Integer> audioIdByKeyword = audioMarkService.getAudioIdListByKeyword(Arrays.asList(pageReqVO.getKeyWord()));
            audioIdList.addAll(audioIdByKeyword);
        }
        if (audioIdList != null && audioIdList.isEmpty()) {
            PageResult<LmAudioDO> pageResult = new PageResult<>(0L);
            return pageResult;
        }

        LmAudioPageReq lmAudioPageReq = BeanUtils.toBean(pageReqVO, LmAudioPageReq.class);
        lmAudioPageReq.setAudioIdList(audioIdList);
        return audioMapper.selectPage(lmAudioPageReq);
    }


    @Override
    public void setRelationContent(List<LmAudioRespVO> audioRespVOS) {
        for (LmAudioRespVO audioRespVO : audioRespVOS) {
            this.setRelationContent(audioRespVO);
        }
    }

    private void setRelationContent(LmAudioRespVO audioRespVO) {
        if (audioRespVO.getRelationContent() != null) {
            List<AudioRelationSaveVo> audioRelationSaveVos = JSON.parseArray(audioRespVO.getRelationContent(), AudioRelationSaveVo.class);
            List<AudioRelationRespVo> audioRelationRespVoList = new ArrayList<>(audioRelationSaveVos.size());
            for (AudioRelationSaveVo audioRelationSaveVo : audioRelationSaveVos) {
                AudioRelationRespVo audioRelationRespVo = new AudioRelationRespVo();
                audioRelationRespVo.setDefaultCon(audioRelationSaveVo.isDefaultCon());
                LmAudioDO audio = this.getAudio(audioRelationSaveVo.getAudioId());
                if (audio != null) {
                    AudioBaseRespVo audioBaseRespVo = this.createAudioBaseResp(audio);
                    audioRelationRespVo.setAudioBaseResp(audioBaseRespVo);
                }
                if (audioRelationSaveVo.getIds() != null || audioRelationSaveVo.getIds().size() > 0) {
                    List<KeyWordDO> keyWordList = keyWordService.getKeyWordList(audioRelationSaveVo.getIds());
                    List<KeyWordRespVO> keyWordRespVOList = BeanUtils.toBean(keyWordList, KeyWordRespVO.class);
                    audioRelationRespVo.setKeywordList(keyWordRespVOList);
                }
                audioRelationRespVoList.add(audioRelationRespVo);
            }
            audioRespVO.setAudioRelationRespVoList(audioRelationRespVoList);
        }
    }

    public AudioBaseRespVo createAudioBaseResp(LmAudioDO audioDO) {
        AudioBaseRespVo audioBaseRespVo = new AudioBaseRespVo();
        audioBaseRespVo.setAudioId(audioDO.getId());
        audioBaseRespVo.setName(audioDO.getName());
        UploadFileResult uploadFileResult = fileService.getFile(audioDO.getFileId(), audioDO.getAudioTime());
        if (uploadFileResult != null) {
            audioBaseRespVo.setUrl(uploadFileResult.getFileUrl());
        }
        return audioBaseRespVo;
    }

}